#include "help.h"

// Windows
static int Begin(lua_State* L){
    bool r = false;
    if(lua_istable(L,2)){
        bool v;
        getbyref(L,2,v);
        r = ImGui::Begin(luaL_checkstring(L,1),&v,luaL_optint(L,3,ImGuiWindowFlags_NoSavedSettings));
        setbyref(L,2,v);
    }else{
        r = ImGui::Begin(luaL_checkstring(L,1),NULL,luaL_optint(L,2,ImGuiWindowFlags_NoSavedSettings));
    }
    lua_pushboolean(L,r);
    return 1;
}

static int End(lua_State* L){
    ImGui::End();
    return 0;
}
//==========================================================================
// Child Windows
static int BeginChild(lua_State* L){
    ImVec2 size(0,0);
    getImVec2(L,2,size);
    bool r;
    if (lua_isinteger(L,1)){
        ImGuiID id = (ImGuiID)luaL_checkint(L,1);
        r = ImGui::BeginChild(id,size,luaL_optboolean(L,4,false),luaL_optint(L,5,0));
    }else
        r = ImGui::BeginChild(luaL_checkstring(L,1),size,luaL_optboolean(L,4,false),luaL_optint(L,5,0));
    lua_pushboolean(L,r);
    return 1;
}

static int EndChild(lua_State* L){
    ImGui::EndChild();
    return 0;
}
//==========================================================================
// Windows Utilities

static int IsWindowAppearing(lua_State* L){
    lua_pushboolean(L,ImGui::IsWindowAppearing());
    return 1;
}

static int IsWindowCollapsed(lua_State* L){
    lua_pushboolean(L,ImGui::IsWindowCollapsed());
    return 1;
}

static int IsWindowFocused(lua_State* L){
    lua_pushboolean(L,ImGui::IsWindowFocused(luaL_optint(L,1,0)));
    return 1;
}

static int IsWindowHovered(lua_State* L){
    lua_pushboolean(L,ImGui::IsWindowHovered(luaL_optint(L,1,0)));
    return 1;
}
//TODO
static int GetWindowDrawList(lua_State* L){
    //ImGui::GetWindowDrawList();
    return 0;
}

static int GetWindowPos(lua_State* L){
    ImVec2 v = ImGui::GetWindowPos();
    pushImVec2(L,v);
    return 2;
}

static int GetWindowSize(lua_State* L){
    ImVec2 v = ImGui::GetWindowSize();
    pushImVec2(L,v);
    return 2;
}

static int GetWindowWidth(lua_State* L){
    lua_pushnumber(L,ImGui::GetWindowWidth());
    return 1;
}

static int GetWindowHeight(lua_State* L){
    lua_pushnumber(L,ImGui::GetWindowHeight());
    return 1;
}
//==========================================================================
// Prefer using SetNextXXX functions (before Begin) rather that SetXXX functions (after Begin).
static int SetNextWindowPos(lua_State* L){
    ImVec2 pos(0,0);
    ImVec2 pivot(0,0);
    getImVec2(L,1,pos);
    getImVec2(L,4,pivot);
    ImGui::SetNextWindowPos(pos,luaL_optint(L,3,0) , pivot);//ImGuiCond_Always
    return 0;
}

static int SetNextWindowSize(lua_State* L){
    ImVec2 size(0,0);
    getImVec2(L,1,size);
    ImGui::SetNextWindowSize(size,luaL_optint(L,3,0));
    return 0;
}

static int SetNextWindowSizeConstraints(lua_State* L){
    ImVec2 min,max;
    getImVec2(L,1,min);
    getImVec2(L,3,max);
    ImGui::SetNextWindowSizeConstraints(min,max);
    return 0;
}

static int SetNextWindowContentSize(lua_State* L){
    ImVec2 v(0,0);
    getImVec2(L,1,v);
    ImGui::SetNextWindowContentSize(v);
    return 0;
}

static int SetNextWindowCollapsed(lua_State* L){
    ImGui::SetNextWindowCollapsed(luaL_checkboolean(L,1),luaL_optint(L,2,0));
    return 0;
}

static int SetNextWindowFocus(lua_State* L){
    ImGui::SetNextWindowFocus();
    return 0;
}

static int SetNextWindowBgAlpha(lua_State* L){
    ImGui::SetNextWindowBgAlpha(luaL_checkfloat(L,1));
    return 0;
}

static int SetWindowPos(lua_State* L){
    ImVec2 v(0,0);
    if (lua_isstring(L,1)){
        getImVec2(L,2,v);
        ImGui::SetWindowPos(luaL_checkstring(L,1),v,luaL_optint(L,4,0));
    }else{
        getImVec2(L,1,v);
        ImGui::SetWindowPos(v,luaL_optint(L,3,0));
    }
    return 0;
}

static int SetWindowSize(lua_State* L){
    ImVec2 v(0,0);
    if (lua_isstring(L,1)){
        getImVec2(L,2,v);
        ImGui::SetWindowSize(luaL_checkstring(L,1),v,luaL_optint(L,4,0));
    }else{
        getImVec2(L,1,v);
        ImGui::SetWindowSize(v,luaL_optint(L,3,0));
    }

    return 0;
}

static int SetWindowCollapsed(lua_State* L){
    if (lua_isstring(L,1))
        ImGui::SetWindowCollapsed(luaL_checkstring(L,1),luaL_checkboolean(L,2),luaL_optint(L,3,0));
    else
        ImGui::SetWindowCollapsed(luaL_checkboolean(L,1),luaL_optint(L,2,0));
    return 0;
}

static int SetWindowFocus(lua_State* L){
    if (lua_isnoneornil(L,1))
        ImGui::SetWindowFocus();
    else
        ImGui::SetWindowFocus(luaL_checkstring(L,1));
    return 0;
}

static int SetWindowFontScale(lua_State* L){
    ImGui::SetWindowFontScale(luaL_checkfloat(L,1));
    return 0;
}
//==========================================================================
// Content region
static int GetContentRegionAvail(lua_State* L) {
    ImVec2 v = ImGui::GetContentRegionAvail();
    pushImVec2(L, v);
    return 2;
}

static int GetContentRegionMax(lua_State* L){
    ImVec2 v = ImGui::GetContentRegionMax();
    pushImVec2(L,v);
    return 2;
}

static int GetWindowContentRegionMin(lua_State* L){
    ImVec2 v = ImGui::GetWindowContentRegionMin();
    pushImVec2(L,v);
    return 2;
}

static int GetWindowContentRegionMax(lua_State* L){
    ImVec2 v = ImGui::GetWindowContentRegionMax();
    pushImVec2(L,v);
    return 2;
}

static int GetWindowContentRegionWidth(lua_State* L){
    lua_pushnumber(L,ImGui::GetWindowContentRegionWidth());
    return 1;
}
//==========================================================================
// Windows Scrolling
static int GetScrollX(lua_State* L){
    lua_pushnumber(L,ImGui::GetScrollX());
    return 1;
}

static int GetScrollY(lua_State* L){
    lua_pushnumber(L,ImGui::GetScrollY());
    return 1;
}

static int SetScrollX(lua_State* L) {
    ImGui::SetScrollX(luaL_checkfloat(L, 1));
    return 0;
}

static int SetScrollY(lua_State* L) {
    ImGui::SetScrollY(luaL_checkfloat(L, 1));
    return 0;
}

static int GetScrollMaxX(lua_State* L){
    lua_pushnumber(L,ImGui::GetScrollMaxX());
    return 1;
}

static int GetScrollMaxY(lua_State* L){
    lua_pushnumber(L,ImGui::GetScrollMaxY());
    return 1;
}

static int SetScrollHereX(lua_State* L){
    ImGui::SetScrollHereX(luaL_optfloat(L,1,0.5f));
    return 0;
}

static int SetScrollHereY(lua_State* L){
    ImGui::SetScrollHereY(luaL_optfloat(L,1,0.5f));
    return 0;
}

static int SetScrollFromPosX(lua_State* L){
    ImGui::SetScrollFromPosX(luaL_optfloat(L,1,0.5f));
    return 0;
}

static int SetScrollFromPosY(lua_State* L){
    ImGui::SetScrollFromPosY(luaL_optfloat(L,1,0.5f));
    return 0;
}
//==========================================================================
// Parameters stacks (shared)
//TODO
static int PushFont(lua_State* L){
    //ImGui::PushFont(ImFont* font);
    return 0;
}

static int PopFont(lua_State* L){
    ImGui::PopFont();
    return 0;
}

static int PushStyleColor(lua_State* L){
    if(lua_istable(L,2)){
        ImVec4 v(0,0,0,0);
        getImVec4(L,2,v);
        ImGui::PushStyleColor(luaL_checkint(L,1), v);
    }else
        ImGui::PushStyleColor(luaL_checkint(L,1), luaL_checkint(L,2));
    return 0;
}

static int PopStyleColor(lua_State* L){
    ImGui::PopStyleColor(luaL_optint(L,1,1));
    return 0;
}

static int PushStyleVar(lua_State* L){
    if (lua_istable(L,2)){
        ImVec2 v(0,0);
        getImVec2(L,2,v);
        ImGui::PushStyleVar(luaL_checkint(L,1), v);
    }else
        ImGui::PushStyleVar(luaL_checkint(L,1), luaL_checkfloat(L,2));

    return 0;
}

static int PopStyleVar(lua_State* L){
    ImGui::PopStyleVar(luaL_optint(L,1,1));
    return 0;
}

static int PushAllowKeyboardFocus(lua_State* L) {
    ImGui::PushAllowKeyboardFocus(luaL_checkboolean(L, 1));
    return 0;
}

static int PopAllowKeyboardFocus(lua_State* L) {
    ImGui::PopAllowKeyboardFocus();
    return 0;
}

static int PushButtonRepeat(lua_State* L) {
    ImGui::PushButtonRepeat(luaL_checkboolean(L, 1));
    return 0;
}

static int PopButtonRepeat(lua_State* L) {
    ImGui::PopButtonRepeat();
    return 0;
}
//==========================================================================
// Parameters stacks (current window)

static int PushItemWidth(lua_State* L) {
    ImGui::PushItemWidth(luaL_checkfloat(L, 1));
    return 0;
}

static int PopItemWidth(lua_State* L) {
    ImGui::PopItemWidth();
    return 0;
}

static int SetNextItemWidth(lua_State* L) {
    ImGui::SetNextItemWidth(luaL_checkfloat(L, 1));
    return 0;
}

static int CalcItemWidth(lua_State* L) {
    lua_pushnumber(L, ImGui::CalcItemWidth());
    return 1;
}

static int PushTextWrapPos(lua_State* L) {
    ImGui::PushTextWrapPos(luaL_checkfloat(L, 1));
    return 0;
}

static int PopTextWrapPos(lua_State* L) {
    ImGui::PopTextWrapPos();
    return 0;
}
//==========================================================================
// Style read access

//TODO
static int GetFont(lua_State* L){
    //ImGui::GetFont()
    return 0;
}

static int GetFontSize(lua_State* L){
    lua_pushnumber(L,ImGui::GetFontSize());
    return 1;
}

static int GetFontTexUvWhitePixel(lua_State* L){
    ImVec2 v = ImGui::GetFontTexUvWhitePixel();
    pushImVec2(L,v);
    return 2;
}

static int GetColorU32(lua_State* L){
    switch (lua_gettop(L))
    {
    case 1:{
        ImU32 v = luaL_checkint(L,1);
        v = ImGui::GetColorU32(v);
        lua_pushinteger(L,v);
        return 1;};
    case 2:{
        ImU32 v;
        ImGuiCol i = luaL_checkint(L,1);
        float alpha_mul = luaL_checkfloat(L,1);
        v = ImGui::GetColorU32(i,alpha_mul);
        lua_pushinteger(L,v);
        return 1;};
    case 4:{
        ImU32 v;
        ImVec4 c;
        getImVec4(L,1,c);
        v = ImGui::GetColorU32(c);
        lua_pushinteger(L,v);
        return 1;};
    }
    return 0;
}

static int GetStyleColorVec4(lua_State* L) {
    ImVec4 v = ImGui::GetStyleColorVec4(luaL_checkint(L, 1));
    pushImVec4(L, v);
    return 4;
}

//==========================================================================
// Cursor / Layout
static int Separator(lua_State* L){
    ImGui::Separator();
    return 0;
}

static int SameLine(lua_State* L){
    ImGui::SameLine(luaL_optfloat(L,1,0.0f),luaL_optfloat(L,2,-1.0f));
    return 0;
}

static int NewLine(lua_State* L){
    ImGui::NewLine();
    return 0;
}

static int Spacing(lua_State* L){
    ImGui::Spacing();
    return 0;
}

static int Dummy(lua_State* L){
    ImVec2 v(0,0);
    getImVec2(L,1,v);
    ImGui::Dummy(v);
    return 0;
}

static int Indent(lua_State* L){
    ImGui::Indent(luaL_optfloat(L,1,0.0f));
    return 0;
}
static int Unindent(lua_State* L){
    ImGui::Unindent(luaL_optfloat(L,1,0.0f));
    return 0;
}

static int BeginGroup(lua_State* L){
    ImGui::BeginGroup();
    return 0;
}

static int EndGroup(lua_State* L){
    ImGui::EndGroup();
    return 0;
}

static int GetCursorPos(lua_State* L){
    ImVec2 v = ImGui::GetCursorPos();
    pushImVec2(L,v);
    return 2;
}

static int GetCursorPosX(lua_State* L){
    lua_pushnumber(L,ImGui::GetCursorPosX());
    return 1;
}

static int GetCursorPosY(lua_State* L){
    lua_pushnumber(L,ImGui::GetCursorPosY());
    return 1;
}

static int SetCursorPos(lua_State* L){
    ImVec2 v(0,0);
    getImVec2(L,1,v);
    ImGui::SetCursorPos(v);
    return 0;
}

static int SetCursorPosX(lua_State* L){
    ImGui::SetCursorPosX(luaL_checkfloat(L,1));
    return 0;
}

static int SetCursorPosY(lua_State* L){
    ImGui::SetCursorPosY(luaL_checkfloat(L,1));
    return 0;
}

static int GetCursorStartPos(lua_State* L){
    ImVec2 v = ImGui::GetCursorStartPos();
    pushImVec2(L,v);
    return 2;
}

static int GetCursorScreenPos(lua_State* L){
    ImVec2 v = ImGui::GetCursorScreenPos();
    pushImVec2(L,v);
    return 2;
}

static int SetCursorScreenPos(lua_State* L){
    ImVec2 v(0,0);
    getImVec2(L,1,v);
    ImGui::SetCursorScreenPos(v);
    return 0;
}

static int AlignTextToFramePadding(lua_State* L){
    ImGui::AlignTextToFramePadding();
    return 0;
}

static int GetTextLineHeight(lua_State* L){
    lua_pushnumber(L,ImGui::GetTextLineHeight());
    return 1;
}

static int GetTextLineHeightWithSpacing(lua_State* L){
    lua_pushnumber(L,ImGui::GetTextLineHeightWithSpacing());
    return 1;
}

static int GetFrameHeight(lua_State* L){
    lua_pushnumber(L,ImGui::GetFrameHeight());
    return 1;
}

static int GetFrameHeightWithSpacing(lua_State* L){
    lua_pushnumber(L,ImGui::GetFrameHeightWithSpacing());
    return 1;
}
//==========================================================================
// ID stack/scopes
static int PushID(lua_State* L){
    if (lua_isinteger(L,1)){
        ImGui::PushID(luaL_checkint(L,1));
    }else if (lua_isstring(L,1) && lua_isstring(L,2)){
        ImGui::PushID(lua_tostring(L,1),lua_tostring(L,2));
    }else if (lua_isstring(L,1)){
        ImGui::PushID(lua_tostring(L,1));
    }
    return 0;
}

static int PopID(lua_State* L){
    ImGui::PopID();
    return 0;
}

static int GetID(lua_State* L){
    if (lua_isstring(L,1) && lua_isstring(L,2))
        lua_pushinteger(L,ImGui::GetID(lua_tostring(L,1),lua_tostring(L,2)));
    else
        lua_pushinteger(L,ImGui::GetID(luaL_checkstring(L,1)));
    return 1;
}
//==========================================================================
// Widgets: Text
static int TextUnformatted(lua_State* L){
    ImGui::TextUnformatted(luaL_optstring(L,1,"nil"),luaL_optstring(L,2,NULL));
    return 0;
}

static int Text(lua_State* L){
    ImGui::Text(luaL_optstring(L,1,"nil"));
    return 0;
}

static int TextColored(lua_State* L){
    ImVec4 col(1,1,1,1);
    getImVec4(L,2,col);
    ImGui::TextColored(col,luaL_optstring(L,1,"nil"));
    return 0;
}

static int TextDisabled(lua_State* L){
    ImGui::TextDisabled(luaL_optstring(L,1,"nil"));
    return 0;
}

static int TextWrapped(lua_State* L){
    ImGui::TextWrapped(luaL_optstring(L,1,"nil"));
    return 0;
}

static int LabelText(lua_State* L){
    ImGui::LabelText(luaL_checkstring(L,1),luaL_optstring(L,2,"nil"));
    return 0;
}

static int BulletText(lua_State* L){
    ImGui::BulletText(luaL_optstring(L,1,"nil"));
    return 0;
}
//==========================================================================
// Widgets: Main
static int Button(lua_State* L){
    ImVec2 v(0,0);
    getImVec2(L,2,v);
    lua_pushboolean(L,ImGui::Button(luaL_checkstring(L,1),v));
    return 1;
}

static int SmallButton(lua_State* L){
    lua_pushboolean(L,ImGui::SmallButton(luaL_checkstring(L,1)));
    return 1;
}

static int InvisibleButton(lua_State* L){
    ImVec2 size(0,0);
    getImVec2(L,2,size);
    lua_pushboolean(L,ImGui::InvisibleButton(luaL_checkstring(L,1),size));
    return 1;
}

static int ArrowButton(lua_State* L){
    bool r = ImGui::ArrowButton(luaL_checkstring(L,1), luaL_optint(L,2,ImGuiDir_None));
    lua_pushboolean(L,r);
    return 1;
}

static int Image(lua_State* L){
    SDL_Texture* tex = (SDL_Texture*)lua_topointer(L,1);
    ImVec2 size(0,0);
    int n = 2;
    if (!getImVec2(L, &n, size))
    {
        int w, h;
        SDL_QueryTexture(tex, NULL, NULL, &w, &h);
        size.x = (float)w;
        size.y = (float)h;
    }
    ImVec2 uv0(0,0);
    getImVec2(L, &n,uv0);
    
    ImVec2 uv1(1,1);
    getImVec2(L, &n,uv1);

    ImVec4 co1(1,1,1,1);
    getImVec4(L, &n,co1);

    ImVec4 co2(0,0,0,0);
    getImVec4(L, &n,co2);

    ImGui::Image(tex,size,uv0,uv1,co1,co2);
    return 0;
}

static int ImageButton(lua_State* L){
    SDL_Texture* tex = (SDL_Texture*)lua_topointer(L, 1);
    ImVec2 size(0,0);
	int n = 2;
	if (!getImVec2(L, &n, size))
	{
		int w, h;
		SDL_QueryTexture(tex, NULL, NULL, &w, &h);
		size.x = (float)w;
		size.y = (float)h;
	}
	ImVec2 uv0(0, 0);
	getImVec2(L, &n, uv0);

	ImVec2 uv1(1, 1);
	getImVec2(L, &n, uv1);

	ImVec4 co1(1, 1, 1, 1);
	getImVec4(L, &n, co1);

	ImVec4 co2(0, 0, 0, 0);
	getImVec4(L, &n, co2);

    int frame_padding = luaL_optint(L, n, -1);
    bool r = ImGui::ImageButton(tex, size, uv0, uv1, frame_padding, co1, co2);
    lua_pushboolean(L,r);
    return 1;
}

static int Checkbox(lua_State* L){
    bool v ;
    getbyref(L,2,v);
    bool r = ImGui::Checkbox(luaL_checkstring(L,1), &v);
    setbyref(L,2,v);
    lua_pushboolean(L,r);
    return 1;
}

static int CheckboxFlags(lua_State* L){
    unsigned int v ;
    getbyref(L,2,v);
    bool r = ImGui::CheckboxFlags(luaL_checkstring(L,1), &v,luaL_checkint(L,3));
    setbyref(L,2,v);
    lua_pushboolean(L,r);
    return 1;
    return 0;
}

static int RadioButton(lua_State* L){
    bool r;
    if(lua_isboolean(L,2)){
        r = ImGui::RadioButton(luaL_checkstring(L,1), luaL_checkboolean(L,2));
    }else{
        int v;
        getbyref(L,2,v);
        r = ImGui::RadioButton(luaL_checkstring(L,1), &v, luaL_checkint(L,3));
        setbyref(L,2,v);
    }

    lua_pushboolean(L,r);
    return 1;
}

static int ProgressBar(lua_State* L){
    ImVec2 size(-1,0);
    getImVec2(L,2,size);
    ImGui::ProgressBar(luaL_checkfloat(L,1),size,luaL_optstring(L,4,NULL));
    return 0;
}

static int Bullet(lua_State* L){
    ImGui::Bullet();
    return 0;
}
//==========================================================================
// Widgets: Combo Box
static int BeginCombo(lua_State* L){
    bool r = ImGui::BeginCombo(luaL_checkstring(L,1),luaL_checkstring(L,2),luaL_optint(L,3,0));
    lua_pushboolean(L,r);
    return 1;
}

static int EndCombo(lua_State* L){
    ImGui::EndCombo();
    return 0;
}

static int Combo(lua_State* L){
    int n ;
    bool r;
    getbyref(L,2,n);--n;
    if(lua_istable(L,3)){
        tabledata data(L,3);
        r = ImGui::Combo(luaL_checkstring(L,1), &n, items_getter,&data,(int)luaL_len(L,3),luaL_optint(L,4,-1));
    }else
        r = ImGui::Combo(luaL_checkstring(L,1), &n, luaL_checklstring(L,3,NULL),luaL_optint(L,4,-1));
    setbyref(L,2,++n);
    lua_pushboolean(L,r);
    return 1;
}
//==========================================================================
// Widgets: Drags
static int DragFloat(lua_State* L){
    float v;
    getbyref(L,2,v);
    bool r = ImGui::DragFloat(luaL_checkstring(L,1), &v, luaL_optfloat(L,3,1.0f),luaL_optfloat(L,4,0.0f),
        luaL_optfloat(L,5,0.0f),luaL_optstring(L,6,"%.3f"),luaL_optfloat(L,7,1.0f));
    setbyref(L,2,v);
    lua_pushboolean(L,r);
    return 1;
}

static int DragFloat2(lua_State* L){
    float v[2];
    getbyreftable(L,2,v);
    bool r = ImGui::DragFloat2(luaL_checkstring(L,1),v,luaL_optfloat(L,3,1.0f),luaL_optfloat(L,4,0.0f),
        luaL_optfloat(L,5,0.0f),luaL_optstring(L,6,"%.3f"),luaL_optfloat(L,7,1.0f));
    setbyreftable(L,2,v);
    lua_pushboolean(L,r);
    return 1;
}

static int DragFloat3(lua_State* L){
    float v[3];
    getbyreftable(L,2,v);
    bool r = ImGui::DragFloat3(luaL_checkstring(L,1),v,luaL_optfloat(L,3,1.0f),luaL_optfloat(L,4,0.0f),
        luaL_optfloat(L,5,0.0f),luaL_optstring(L,6,"%.3f"),luaL_optfloat(L,7,1.0f));
    setbyreftable(L,2,v);
    lua_pushboolean(L,r);
    return 1;
}

static int DragFloat4(lua_State* L){
    float v[4];
    getbyreftable(L,2,v);
    bool r = ImGui::DragFloat4(luaL_checkstring(L,1),v,luaL_optfloat(L,3,1.0f),luaL_optfloat(L,4,0.0f),
        luaL_optfloat(L,5,0.0f),luaL_optstring(L,6,"%.3f"),luaL_optfloat(L,7,1.0f));
    setbyreftable(L,2,v);
    lua_pushboolean(L,r);
    return 1;
}

static int DragFloatRange2(lua_State* L){
    float min,max;
    getbyref(L,2,min);getbyref(L,3,max);
    bool r = ImGui::DragFloatRange2(luaL_checkstring(L,1),&min,&max,luaL_optfloat(L,4,0.0f),
        luaL_optfloat(L,5,0.0f),luaL_optfloat(L,6,0.0f),luaL_optstring(L,7,"%.3f"),
        luaL_optstring(L,8,NULL),(ImGuiSliderFlags)luaL_optfloat(L,9,1.0f));
    setbyref(L,2,min);setbyref(L,3,max);
    lua_pushboolean(L,r);
    return 1;
}

static int DragInt(lua_State* L){
    int v;
    getbyref(L,2,v);
    bool r = ImGui::DragInt(luaL_checkstring(L,1), &v, luaL_optfloat(L,3,1.0f),luaL_optint(L,4,0),
        luaL_optint(L,5,0),luaL_optstring(L,6,"%d"));
    setbyref(L,2,v);
    lua_pushboolean(L,r);
    return 1;
}

static int DragInt2(lua_State* L){
    int v[2];
    getbyreftable(L,2,v);
    bool r = ImGui::DragInt2(luaL_checkstring(L,1),v,luaL_optfloat(L,3,1.0f),luaL_optint(L,4,0),
        luaL_optint(L,5,0),luaL_optstring(L,6,"%d"));
    setbyreftable(L,2,v);
    lua_pushboolean(L,r);
    return 1;
}

static int DragInt3(lua_State* L){
    int v[3];
    getbyreftable(L,2,v);
    bool r = ImGui::DragInt3(luaL_checkstring(L,1),v,luaL_optfloat(L,3,1.0f),luaL_optint(L,4,0),
        luaL_optint(L,5,0),luaL_optstring(L,6,"%d"));
    setbyreftable(L,2,v);
    lua_pushboolean(L,r);
    return 1;
}

static int DragInt4(lua_State* L){
    int v[4];
    getbyreftable(L,2,v);
    bool r = ImGui::DragInt4(luaL_checkstring(L,1),v,luaL_optfloat(L,3,1.0f),luaL_optint(L,4,0),
        luaL_optint(L,5,0),luaL_optstring(L,6,"%d"));
    setbyreftable(L,2,v);
    lua_pushboolean(L,r);
    return 1;
}

static int DragIntRange2(lua_State* L){
    int min,max;
    getbyref(L,2,min);getbyref(L,3,max);
    bool r = ImGui::DragIntRange2(luaL_checkstring(L,1),&min,&max,
        luaL_optfloat(L,4,1.0f),
        luaL_optint(L,5,0),luaL_optint(L,6,0),
        luaL_optstring(L,7,"%d"),
        luaL_optstring(L,8,NULL));
    setbyref(L,2,min);setbyref(L,3,max);
    lua_pushboolean(L,r);
    return 1;
}
////TODO
//static int DragScalar(lua_State* L){
//  //bool r = ImGui::DragScalar(luaL_checkstring(L,1),);
//    return 0;
//}
//
//static int DragScalarN(lua_State* L) {
//  //bool r = ImGui::DragScalar(luaL_checkstring(L,1),);
//  return 0;
//}
//==========================================================================
// Widgets: Sliders
static int SliderFloat(lua_State* L){
    float v ;
    getbyref(L,2,v);
    bool r = ImGui::SliderFloat(luaL_checkstring(L,1), &v, luaL_checkfloat(L,3), luaL_checkfloat(L,4),
        luaL_optstring(L,5,"%.3f"),luaL_optfloat(L,6,1.0f));
    setbyref(L,2,v);
    lua_pushboolean(L,r);
    return 1;
}

static int SliderFloat2(lua_State* L){
    float v[2];
    getbyreftable(L,2,v);
    bool r = ImGui::SliderFloat2(luaL_checkstring(L,1),v,luaL_optfloat(L,3,1.0f),luaL_optfloat(L,4,0.0f),
        luaL_optstring(L,5,"%.3f"),luaL_optfloat(L,6,1.0f));
    setbyreftable(L,2,v);
    lua_pushboolean(L,r);
    return 1;
}

static int SliderFloat3(lua_State* L){
    float v[3];
    getbyreftable(L,2,v);
    bool r = ImGui::SliderFloat3(luaL_checkstring(L,1),v,luaL_optfloat(L,3,1.0f),luaL_optfloat(L,4,0.0f),
        luaL_optstring(L,5,"%.3f"),luaL_optfloat(L,6,1.0f));
    setbyreftable(L,2,v);
    lua_pushboolean(L,r);
    return 1;
}

static int SliderFloat4(lua_State* L){
    float v[4];
    getbyreftable(L,2,v);
    bool r = ImGui::SliderFloat4(luaL_checkstring(L,1),v,luaL_optfloat(L,3,1.0f),luaL_optfloat(L,4,0.0f),
        luaL_optstring(L,5,"%.3f"),luaL_optfloat(L,6,1.0f));
    setbyreftable(L,2,v);
    lua_pushboolean(L,r);
    return 1;
}

static int SliderAngle(lua_State* L){
    float v;
    getbyref(L,2,v);
    bool r = ImGui::SliderAngle(luaL_checkstring(L,1),&v,luaL_optfloat(L,3,-360.0f),luaL_optfloat(L,4,+360.0f),
        luaL_optstring(L,5,"%.0f deg"));
    setbyref(L,2,v);
    lua_pushboolean(L,r);
    return 1;
}

static int SliderInt(lua_State* L){
    int v ;
    getbyref(L,2,v);
    bool r = ImGui::SliderInt(luaL_checkstring(L,1), &v, luaL_checkint(L,3), luaL_checkint(L,4),
        luaL_optstring(L,5,"%d"));
    setbyref(L,2,v);
    lua_pushboolean(L,r);
    return 1;
}

static int SliderInt2(lua_State* L){
    int v[2];
    getbyreftable(L,2,v);
    bool r = ImGui::SliderInt2(luaL_checkstring(L,1),v,luaL_checkint(L,3),luaL_checkint(L,4),
        luaL_optstring(L,5,"%d"));
    setbyreftable(L,2,v);
    lua_pushboolean(L,r);
    return 1;
}

static int SliderInt3(lua_State* L){
    int v[3];
    getbyreftable(L,2,v);
    bool r = ImGui::SliderInt3(luaL_checkstring(L,1),v,luaL_checkint(L,3),luaL_checkint(L,4),
        luaL_optstring(L,5,"%d"));
    setbyreftable(L,2,v);
    lua_pushboolean(L,r);
    return 1;
}

static int SliderInt4(lua_State* L){
    int v[4];
    getbyreftable(L,2,v);
    bool r = ImGui::SliderInt4(luaL_checkstring(L,1),v,luaL_checkint(L,3),luaL_checkint(L,4),
        luaL_optstring(L,5,"%d"));
    setbyreftable(L,2,v);
    lua_pushboolean(L,r);
    return 1;
}

static int SliderScalar(lua_State* L){
    double v;
    double min = luaL_checkfloat(L,3);
    double max = luaL_checkfloat(L,4);
    getbyref(L,2,v);
    bool r = ImGui::SliderScalar(luaL_checkstring(L,1), ImGuiDataType_Double, &v, &min, &max,luaL_optstring(L,5,"%d"),luaL_optfloat(L,6,1.0f));
    setbyref(L,2,v);
    lua_pushboolean(L,r);
    return 1;
}
//TODO SliderScalarN
static int VSliderFloat(lua_State* L){
    float v;
    ImVec2 size;
    getbyref(L,3,v);
    gettableVec2(L,2,size);
    bool r = ImGui::VSliderFloat(luaL_checkstring(L,1),size ,&v,luaL_checkfloat(L,4),luaL_checkfloat(L,5),luaL_optstring(L,6,"%.3f"),(ImGuiSliderFlags)luaL_optfloat(L,7,1.0f));
    setbyref(L,3,v);
    lua_pushboolean(L,r);
    return 1;
    return 0;
}

static int VSliderInt(lua_State* L){
    int v;
    ImVec2 size;
    getbyref(L,3,v);
    gettableVec2(L,2,size);
    bool r = ImGui::VSliderInt(luaL_checkstring(L,1),size ,&v,luaL_checkint(L,4),luaL_checkint(L,5),luaL_optstring(L,6,"%d"));
    setbyref(L,3,v);
    lua_pushboolean(L,r);
    return 1;
}
//TODO
static int VSliderScalar(lua_State* L){

    return 0;
}
//==========================================================================
// Widgets: Input with Keyboard

static int InputText(lua_State* L){
    char *buf;
    size_t buf_size;
    getinputbuf(L,2,buf,buf_size);
    bool r = ImGui::InputText(luaL_checkstring(L,1),buf, buf_size);
    if (r)
        setinputbuf(L,2,buf);
    lua_pushboolean(L,r);
    return 1;
}

static int InputTextMultiline(lua_State* L){
    ImVec2 size(0,0);
    char *buf ;
    size_t buf_size;
    getinputbuf(L,2,buf,buf_size);
    getImVec2(L,3,size);
    bool r = ImGui::InputTextMultiline(luaL_checkstring(L,1),buf,buf_size,size,luaL_optint(L,5,0));
    if (r)
        setinputbuf(L,2,buf);
    lua_pushboolean(L,r);
    return 1;
}

static int InputTextWithHint(lua_State* L){
    char *buf;
    size_t buf_size;
    getinputbuf(L,3,buf,buf_size);
    bool r = ImGui::InputTextWithHint(luaL_checkstring(L,1),luaL_checkstring(L,2),buf, buf_size,luaL_optint(L,4,0));
    if (r)
        setinputbuf(L,3,buf);
    lua_pushboolean(L,r);
    return 1;
}

static int InputFloat(lua_State* L){
    float v;
    getbyref(L,2,v);
    bool r = ImGui::InputFloat(luaL_checkstring(L,1), &v, luaL_checkfloat(L,3),luaL_optfloat(L,4,0.0f),
        luaL_optstring(L,5,"%.3f"),luaL_optint(L,6,0));
    if (r)
        setbyref(L,2,v);
    lua_pushboolean(L,r);
    return 1;
}

static int InputFloat2(lua_State* L){
    float v[2];
    getbyreftable(L,2,v);
    bool r = ImGui::InputFloat2(luaL_checkstring(L,1), v,luaL_optstring(L,3,"%.3f"),luaL_optint(L,4,0));
    if (r)
        setbyreftable(L,2,v);
    lua_pushboolean(L,r);
    return 1;
}

static int InputFloat3(lua_State* L){
    float v[3];
    getbyreftable(L,2,v);
    bool r = ImGui::InputFloat3(luaL_checkstring(L,1), v,luaL_optstring(L,3,"%.3f"),luaL_optint(L,4,0));
    if (r)
        setbyreftable(L,2,v);
    lua_pushboolean(L,r);
    return 1;
}

static int InputFloat4(lua_State* L){
    float v[4];
    getbyreftable(L,2,v);
    bool r = ImGui::InputFloat4(luaL_checkstring(L,1), v,luaL_optstring(L,3,"%.3f"),luaL_optint(L,4,0));
    if (r)
        setbyreftable(L,2,v);
    lua_pushboolean(L,r);
    return 1;
}

static int InputInt(lua_State* L){
    int v ;
    getbyref(L,2,v);
    bool r = ImGui::InputInt(luaL_checkstring(L,1), &v, luaL_optint(L,3,0),luaL_optint(L,4,100),
        luaL_optint(L,5,0));
    if (r)
        setbyref(L,2,v);
    lua_pushboolean(L,r);
    return 1;
}

static int InputInt2(lua_State* L){
    int v[2];
    getbyreftable(L,2,v);
    bool r = ImGui::InputInt2(luaL_checkstring(L,1), v,luaL_optint(L,3,0));
    if (r)
        setbyreftable(L,2,v);
    lua_pushboolean(L,r);
    return 1;
}

static int InputInt3(lua_State* L){
    int v[3];
    getbyreftable(L,2,v);
    bool r = ImGui::InputInt3(luaL_checkstring(L,1), v,luaL_optint(L,3,0));
    if (r)
        setbyreftable(L,2,v);
    lua_pushboolean(L,r);
    return 1;
}

static int InputInt4(lua_State* L){
    int v[4];
    getbyreftable(L,2,v);
    bool r = ImGui::InputInt4(luaL_checkstring(L,1), v,luaL_optint(L,3,0));
    if (r)
        setbyreftable(L,2,v);
    lua_pushboolean(L,r);
    return 1;
}

static int InputDouble(lua_State* L){
    double v;
    getbyref(L,2,v);
    bool r = ImGui::InputDouble(luaL_checkstring(L,1), &v, luaL_checknumber(L,3),luaL_optnumber(L,4,0.0f),
        luaL_optstring(L,5,"%.6f"),luaL_optint(L,6,0));
    if (r)
        setbyref(L,2,v);
    lua_pushboolean(L,r);
    return 1;
}
//TODO
static int InputScalar(lua_State* L){
    //ImGui::InputScalar();
    return 0;
}
//TODO InputScalarN
//==========================================================================
// Widgets: Color Editor/Picker
static int ColorEdit3(lua_State* L){
    ImVec4 v(0,0,0,0);
    gettableVec4(L,2,v);
    bool r = ImGui::ColorEdit3(luaL_checkstring(L,1), (float*)&v);
    settableVec4(L,2,v);
    lua_pushboolean(L,r);
    return 1;
}

static int ColorEdit4(lua_State* L){
    ImVec4 v(0,0,0,0);
    gettableVec4(L,2,v);
    bool r = ImGui::ColorEdit4(luaL_checkstring(L,1), (float*)&v);
    settableVec4(L,2,v);
    lua_pushboolean(L,r);
    return 1;
}

static int ColorPicker3(lua_State* L){
    ImVec4 v(0,0,0,0);
    gettableVec4(L,2,v);
    bool r = ImGui::ColorPicker3(luaL_checkstring(L,1), (float*)&v);
    settableVec4(L,2,v);
    lua_pushboolean(L,r);
    return 1;
}

static int ColorPicker4(lua_State* L){
    ImVec4 v(0,0,0,0);
    gettableVec4(L,2,v);
    bool r = ImGui::ColorPicker4(luaL_checkstring(L,1), (float*)&v);
    settableVec4(L,2,v);
    lua_pushboolean(L,r);
    return 1;
}

static int ColorButton(lua_State* L){
    ImVec4 v(0,0,0,0);
    ImVec2 size(0,0);
    gettableVec4(L,2,v);
    gettableVec2(L,4,size);
    bool r = ImGui::ColorButton(luaL_checkstring(L,1),v,luaL_optint(L,3,0),size);
    settableVec4(L,2,v);
    settableVec2(L,4,size);
    lua_pushboolean(L,r);
    return 1;
}

static int SetColorEditOptions(lua_State* L){
    ImGui::SetColorEditOptions(luaL_checkint(L,1));
    return 0;
}
//==========================================================================
// Widgets: Trees
static int TreeNode(lua_State* L){
    //TODO
    lua_pushboolean(L,ImGui::TreeNode(luaL_checkstring(L,1)));
    return 1;
}
//TreeNodeV
static int TreeNodeEx(lua_State* L){
    //TODO
    lua_pushboolean(L,ImGui::TreeNodeEx(luaL_checkstring(L,1),luaL_optint(L,2,0)));
    return 1;
}

static int TreePush(lua_State* L){
    //TODO
    ImGui::TreePush(luaL_checkstring(L,1));
    return 0;
}

static int TreePop(lua_State* L){
    ImGui::TreePop();
    return 0;
}

static int GetTreeNodeToLabelSpacing(lua_State* L){
    lua_pushnumber(L,ImGui::GetTreeNodeToLabelSpacing());
    return 1;
}

static int CollapsingHeader(lua_State* L){
    if (lua_istable(L,2)){
        bool v;
        getbyref(L,2,v);
        lua_pushboolean(L,ImGui::CollapsingHeader(luaL_checkstring(L,1),&v,luaL_optint(L,3,0)));
        setbyref(L,2,v);
    }else
        lua_pushboolean(L,ImGui::CollapsingHeader(luaL_checkstring(L,1),luaL_optint(L,2,0)));
    return 1;
}

static int SetNextItemOpen(lua_State* L){
    ImGui::SetNextItemOpen(luaL_checkboolean(L,1),luaL_optint(L,2,0));
    return 0;
}
//==========================================================================
// Widgets: Selectables
static int Selectable(lua_State* L){
    bool r;
    ImVec2 size(0,0);
    getImVec2(L,4,size);
    if (lua_istable(L,2)){
        bool v;
        getbyref(L,2,v);
        r = ImGui::Selectable(luaL_checkstring(L,1),&v,luaL_optint(L,3,0),size);
        setbyref(L,2,v);
    }else
        r = ImGui::Selectable(luaL_checkstring(L,1),luaL_optboolean(L,2,false),luaL_optint(L,3,0),size);
    lua_pushboolean(L,r);
    return 1;
}
//==========================================================================
// Widgets: List Boxes

static int BeginListBox(lua_State* L){
    bool r = false;
    if (lua_istable(L,2)){
        ImVec2 size(0,0);
        gettableVec2(L,2,size);
        r = ImGui::BeginListBox(luaL_checkstring(L,1),size);
    }
    lua_pushboolean(L,r);
    return 1;
}

static int EndListBox(lua_State* L){
    ImGui::EndListBox();
    return 0;
}

static int ListBox(lua_State* L) {
    int v;
    getbyref(L, 2, v); --v;
    tabledata data(L, 3);
    bool r = ImGui::ListBox(luaL_checkstring(L, 1), &v, items_getter, &data, (int)luaL_len(L, 3), luaL_optint(L, 4, -1));
    setbyref(L, 2, ++v);
    lua_pushboolean(L, r);
    return 1;
}

//==========================================================================
// Widgets: Data Plotting

static int PlotLines(lua_State* L){
    tabledata data(L,2);
    ImVec2 size(0,0);
    gettableVec2(L,7,size);
    ImGui::PlotLines(luaL_checkstring(L,1),values_getter,&data,(int)luaL_len(L,2),luaL_optint(L,3,0),
        luaL_optstring(L,4,NULL),luaL_optfloat(L,5,FLT_MAX),luaL_optfloat(L,6,FLT_MAX),size);
    return 0;
}

static int PlotHistogram(lua_State* L){
    tabledata data(L,2);
    ImVec2 size(0,0);
    gettableVec2(L,7,size);
    ImGui::PlotHistogram(luaL_checkstring(L,1),values_getter,&data,(int)luaL_len(L,2),luaL_optint(L,3,0),
        luaL_optstring(L,4,NULL),luaL_optfloat(L,5,FLT_MAX),luaL_optfloat(L,6,FLT_MAX),size);
    return 0;
}
//==========================================================================
// Widgets: Value() Helpers.
static int Value(lua_State* L){
    ImGui::TextUnformatted(lua_tostring(L,1));
    return 0;
}
//==========================================================================
// Widgets: Menus
static int BeginMenuBar(lua_State* L){
    lua_pushboolean(L,ImGui::BeginMenuBar());
    return 1;
}

static int EndMenuBar(lua_State* L){
    ImGui::EndMenuBar();
    return 0;
}

static int BeginMainMenuBar(lua_State* L){
    lua_pushboolean(L,ImGui::BeginMainMenuBar());
    return 1;
}

static int EndMainMenuBar(lua_State* L){
    ImGui::EndMainMenuBar();
    return 0;
}

static int BeginMenu(lua_State* L){
    lua_pushboolean(L,ImGui::BeginMenu(luaL_checkstring(L,1),luaL_optboolean(L,2,true)));
    return 1;
}

static int EndMenu(lua_State* L){
    ImGui::EndMenu();
    return 0;
}

static int MenuItem(lua_State* L){
    bool r;
    if(lua_istable(L,3)){
        bool v;
        getbyref(L,3,v);
        r = ImGui::MenuItem(luaL_checkstring(L,1),luaL_optstring(L,2,NULL),&v,luaL_optboolean(L,4,true));
        setbyref(L,3,v);
    }else
        r = ImGui::MenuItem(luaL_checkstring(L,1),luaL_optstring(L,2,NULL),luaL_optboolean(L,3,false),luaL_optboolean(L,4,true));

    lua_pushboolean(L,r);
    return 1;
}
//==========================================================================
// Tooltips
static int BeginTooltip(lua_State* L){
    ImGui::BeginTooltip();
    return 0;
}

static int EndTooltip(lua_State* L){
    ImGui::EndTooltip();
    return 0;
}

static int SetTooltip(lua_State* L){
    ImGui::SetTooltip(luaL_checkstring(L,1));
    return 0;
}
//==========================================================================
// Popups, Modals

static int BeginPopup(lua_State* L){
    lua_pushboolean(L,ImGui::BeginPopup(luaL_checkstring(L,1),luaL_optint(L,2,0)));
    return 1;
}

static int BeginPopupModal(lua_State* L) {
    bool r;
    if (lua_istable(L, 2)) {
        bool v;
        getbyref(L, 2, v);
        r = ImGui::BeginPopupModal(luaL_checkstring(L, 1), &v, luaL_optint(L, 3, 0));
        setbyref(L, 2, v);
    }
    else
        r = ImGui::BeginPopupModal(luaL_checkstring(L, 1), NULL, luaL_optint(L, 2, 0));

    lua_pushboolean(L, r);
    return 1;
}

static int EndPopup(lua_State* L) {
    ImGui::EndPopup();
    return 0;
}

static int OpenPopup(lua_State* L) {
    ImGui::OpenPopup(luaL_checkstring(L, 1));
    return 0;
}

static int OpenPopupOnItemClick(lua_State* L) {
    ImGui::OpenPopupOnItemClick(luaL_optstring(L, 1, NULL), luaL_optint(L, 2, 1));
    return 0;
}

static int CloseCurrentPopup(lua_State* L) {
    ImGui::CloseCurrentPopup();
    return 0;
}

static int BeginPopupContextItem(lua_State* L){
    bool r = ImGui::BeginPopupContextItem(luaL_optstring(L,1,NULL),luaL_optint(L,2,1));
    lua_pushboolean(L,r);
    return 1;
}

static int BeginPopupContextWindow(lua_State* L){
    bool r = ImGui::BeginPopupContextWindow(luaL_optstring(L,1,NULL),luaL_optint(L,2,1));
    lua_pushboolean(L,r);
    return 1;
}

static int BeginPopupContextVoid(lua_State* L){
    bool r = ImGui::BeginPopupContextVoid(luaL_optstring(L,1,NULL),luaL_optint(L,2,1));
    lua_pushboolean(L,r);
    return 1;
}

static int IsPopupOpen(lua_State* L){
    bool r = ImGui::IsPopupOpen(luaL_checkstring(L,1));
    lua_pushboolean(L,r);
    return 1;
}
//==========================================================================
// Tables
static int BeginTable(lua_State* L){
    const char* str_id = luaL_checkstring(L, 1);
    int colume = (int)luaL_checkinteger(L, 2);
    ImGuiTabItemFlags flags = (ImGuiTabItemFlags)luaL_optinteger(L, 3, 0);
    ImVec2 outer_size = ImVec2(0.0f, 0.0f);
    getImVec2(L, 4, outer_size);
    float inner_width = (float)luaL_optnumber(L, 5, 0.0f);
    bool r = ImGui::BeginTable(str_id, colume, flags, outer_size, inner_width);
    lua_pushboolean(L, r);
    return 1;
}

static int EndTable(lua_State* L){
    ImGui::EndTable();
    return 0;
}

static int TableNextRow(lua_State* L){
    ImGuiTableRowFlags row_flags = (ImGuiTableRowFlags)luaL_optinteger(L,1,0);
    float min_row_height = (float)luaL_optnumber(L,2,0.0f);
    ImGui::TableNextRow(row_flags, min_row_height);

    return 0;
}

static int TableNextColumn(lua_State* L){
    lua_pushboolean(L, ImGui::TableNextColumn());
    return 1;
}

static int TableSetColumnIndex(lua_State* L){
    int column_n = (int)luaL_checkinteger(L, 1);
    lua_pushboolean(L,ImGui::TableSetColumnIndex(column_n));
    return 1;
}

static int TableSetupColumn(lua_State* L){
    const char* label = luaL_checkstring(L, 1);
    ImGuiTableColumnFlags flags = (ImGuiTableColumnFlags)luaL_optinteger(L, 2, ImGuiTableColumnFlags_None);
    float init_width_or_weight = (float)luaL_optnumber(L, 3, 0.0f);
    ImU32 user_id = (ImU32)luaL_optinteger(L, 4, 0);
    ImGui::TableSetupColumn(label, flags, init_width_or_weight, user_id);
    return 0;
}

static int TableSetupScrollFreeze(lua_State* L){
    int cols = (int)luaL_checkinteger(L, 1);
    int rows = (int)luaL_checkinteger(L, 2);
    ImGui::TableSetupScrollFreeze(cols, rows);
    return 0;
}

static int TableHeadersRow(lua_State* L){
    ImGui::TableHeadersRow();
    return 0;
}

static int TableHeader(lua_State* L){
    const char* label = luaL_checkstring(L, 1);
    ImGui::TableHeader(label);
    return 0;
}
//TODO
static int TableGetSortSpecs(lua_State* L)
{
    return 0;
}

static int TableGetColumnCount(lua_State* L){
    lua_pushinteger(L, ImGui::TableGetColumnCount());
    return 1;
}

static int TableGetColumnIndex(lua_State* L){
    lua_pushinteger(L, ImGui::TableGetColumnIndex());
    return 1;
}

static int TableGetRowIndex(lua_State* L){
    lua_pushinteger(L, ImGui::TableGetRowIndex());
    return 1;
}

static int TableGetColumnName(lua_State* L){
    int column_n = (int)luaL_optinteger(L, 1, -1);
    lua_pushstring(L, ImGui::TableGetColumnName(column_n));
    return 1;
}

static int TableGetColumnFlags(lua_State* L){
    int column_n = (int)luaL_optinteger(L, 1, -1);
    lua_pushinteger(L, ImGui::TableGetColumnFlags(column_n));
    return 1;
}

static int TableSetBgColor(lua_State* L){
    ImGuiTableBgTarget target = (ImGuiTableBgTarget)luaL_checkinteger(L, 1);
    ImU32 color = (ImU32)luaL_checkinteger(L, 2);
    int column_n = (int)luaL_optinteger(L, 3, -1);
    ImGui::TableSetBgColor(target, color, column_n);
    return 0;
}

//==========================================================================
// Columns
static int Columns(lua_State* L){
    ImGui::Columns(luaL_optint(L,1,1), luaL_optstring(L,2,NULL), luaL_optboolean(L,3,true));
    return 0;
}

static int NextColumn(lua_State* L){
    ImGui::NextColumn();
    return 0;
}

static int GetColumnIndex(lua_State* L){
    lua_pushinteger(L,ImGui::GetColumnIndex());
    return 1;
}

static int GetColumnWidth(lua_State* L){
    lua_pushnumber(L,ImGui::GetColumnWidth(luaL_optint(L,1,-1)));
    return 1;
}

static int SetColumnWidth(lua_State* L){
    ImGui::SetColumnWidth(luaL_checkint(L,1),luaL_checkfloat(L,2));
    return 0;
}

static int GetColumnOffset(lua_State* L){
    lua_pushnumber(L,ImGui::GetColumnOffset(luaL_optint(L,1,-1)));
    return 0;
}

static int SetColumnOffset(lua_State* L){
    ImGui::SetColumnOffset(luaL_checkint(L,1),luaL_checkfloat(L,2));
    return 0;
}

static int GetColumnsCount(lua_State* L){
    lua_pushinteger(L,ImGui::GetColumnsCount());
    return 1;
}
//==========================================================================
// Tab Bars, Tabs
static int BeginTabBar(lua_State* L){
    bool r = ImGui::BeginTabBar(luaL_checkstring(L,1),luaL_optint(L,2,ImGuiTabBarFlags_None));
    lua_pushboolean(L,r);
    return 1;
}

static int EndTabBar(lua_State* L){
    ImGui::EndTabBar();
    return 0;
}

static int BeginTabItem(lua_State* L){
    bool r ;
    if (lua_istable(L,2)){
        bool v;
        getbyref(L,2,v);
        r = ImGui::BeginTabItem(luaL_checkstring(L,1),&v,luaL_optint(L,3,ImGuiTabItemFlags_None));
        setbyref(L,2,v);
    }else
        r = ImGui::BeginTabItem(luaL_checkstring(L,1),NULL,luaL_optint(L,2,ImGuiTabItemFlags_None));
    lua_pushboolean(L,r);
    return 1;
}

static int EndTabItem(lua_State* L){
    ImGui::EndTabItem();
    return 0;
}
//TODO TabItemButton
static int SetTabItemClosed(lua_State* L){
    ImGui::SetTabItemClosed(luaL_checkstring(L,1));
    return 0;
}
//==========================================================================
// Logging/Capture
static int LogToTTY(lua_State* L){
    ImGui::LogToTTY(luaL_optint(L,1,-1));
    return 0;
}

static int LogToFile(lua_State* L){
    ImGui::LogToFile(luaL_optint(L,1,-1),luaL_optstring(L,2,NULL));
    return 0;
}

static int LogToClipboard(lua_State* L){
    ImGui::LogToClipboard(luaL_optint(L,1,-1));
    return 0;
}

static int LogFinish(lua_State* L){
    ImGui::LogFinish();
    return 0;
}

static int LogButtons(lua_State* L){
    ImGui::LogButtons();
    return 0;
}

static int LogText(lua_State* L){
    ImGui::LogText(luaL_checkstring(L,1));
    return 0;
}
//==========================================================================
// Drag and Drop
static int BeginDragDropSource(lua_State* L){
    lua_pushboolean(L,ImGui::BeginDragDropSource(luaL_optint(L,1,0)));
    return 1;
}

static int SetDragDropPayload(lua_State* L){
    bool r = ImGui::SetDragDropPayload(luaL_checkstring(L,1),luaL_checkstring(L,2),luaL_len(L,2),luaL_optint(L,3,0));
    lua_pushboolean(L,r);
    return 1;
}

static int EndDragDropSource(lua_State* L){
    ImGui::EndDragDropSource();
    return 0;
}

static int BeginDragDropTarget(lua_State* L){
    lua_pushboolean(L,ImGui::BeginDragDropTarget());
    return 1;
}

static int AcceptDragDropPayload(lua_State* L){
    const ImGuiPayload* v = ImGui::AcceptDragDropPayload(luaL_checkstring(L,1),luaL_optint(L,2,0));
    lua_createtable(L,0,7);
    lua_pushlstring(L,(char*)v->Data,v->DataSize);
    lua_setfield(L,-2,"Data");
    lua_pushinteger(L,v->SourceId);
    lua_setfield(L,-2,"SourceId");
    lua_pushinteger(L,v->SourceParentId);
    lua_setfield(L,-2,"SourceParentId");
    lua_pushinteger(L,v->DataFrameCount);
    lua_setfield(L,-2,"DataFrameCount");
    lua_pushlstring(L,v->DataType,32);
    lua_setfield(L,-2,"DataType");
    lua_pushboolean(L,v->Preview);
    lua_setfield(L,-2,"Preview");
    lua_pushboolean(L,v->Delivery);
    lua_setfield(L,-2,"Delivery");
    return 1;
}

static int EndDragDropTarget(lua_State* L){
    ImGui::EndDragDropTarget();
    return 0;
}

static int GetDragDropPayload(lua_State* L){
    const ImGuiPayload* v = ImGui::GetDragDropPayload();
    lua_createtable(L,0,7);
    lua_pushlstring(L,(char*)v->Data,v->DataSize);
    lua_setfield(L,-2,"Data");
    lua_pushinteger(L,v->SourceId);
    lua_setfield(L,-2,"SourceId");
    lua_pushinteger(L,v->SourceParentId);
    lua_setfield(L,-2,"SourceParentId");
    lua_pushinteger(L,v->DataFrameCount);
    lua_setfield(L,-2,"DataFrameCount");
    lua_pushlstring(L,v->DataType,32);
    lua_setfield(L,-2,"DataType");
    lua_pushboolean(L,v->Preview);
    lua_setfield(L,-2,"Preview");
    lua_pushboolean(L,v->Delivery);
    lua_setfield(L,-2,"Delivery");
    return 1;
}
//==========================================================================
// Clipping
static int PushClipRect(lua_State* L){
    ImVec2 min,max;
    gettableVec2(L,1,min);
    gettableVec2(L,2,max);
    ImGui::PushClipRect(min,max,luaL_checkboolean(L,3));
    settableVec2(L,1,min);
    settableVec2(L,2,max);
    return 0;
}

static int PopClipRect(lua_State* L){
    ImGui::PopClipRect();
    return 0;
}
// Focus, Activation
static int SetItemDefaultFocus(lua_State* L){
    ImGui::SetItemDefaultFocus();
    return 0;
}
static int SetKeyboardFocusHere(lua_State* L){
    ImGui::SetKeyboardFocusHere(luaL_optint(L,1,0));
    return 0;
}
//==========================================================================
// Item/Widgets Utilities
static int IsItemHovered(lua_State* L){
    lua_pushboolean(L,ImGui::IsItemHovered(luaL_optint(L,1,ImGuiHoveredFlags_None)));
    return 1;
}

static int IsItemActive(lua_State* L){
    lua_pushboolean(L,ImGui::IsItemActive());
    return 1;
}

static int IsItemFocused(lua_State* L){
    lua_pushboolean(L,ImGui::IsItemFocused());
    return 1;
}

static int IsItemClicked(lua_State* L){
    lua_pushboolean(L,ImGui::IsItemClicked(luaL_optint(L,1,0)));
    return 1;
}

static int IsItemVisible(lua_State* L){
    lua_pushboolean(L,ImGui::IsItemVisible());
    return 1;
}

static int IsItemEdited(lua_State* L){
    lua_pushboolean(L,ImGui::IsItemEdited());
    return 1;
}

static int IsItemActivated(lua_State* L){
    lua_pushboolean(L,ImGui::IsItemActivated());
    return 1;
}

static int IsItemDeactivated(lua_State* L){
    lua_pushboolean(L,ImGui::IsItemDeactivated());
    return 1;
}

static int IsItemDeactivatedAfterEdit(lua_State* L){
    lua_pushboolean(L,ImGui::IsItemDeactivatedAfterEdit());
    return 1;
}

static int IsItemToggledOpen(lua_State* L){
    lua_pushboolean(L,ImGui::IsItemToggledOpen());
    return 1;
}

static int IsAnyItemHovered(lua_State* L){
    lua_pushboolean(L,ImGui::IsAnyItemHovered());
    return 1;
}

static int IsAnyItemActive(lua_State* L){
    lua_pushboolean(L,ImGui::IsAnyItemActive());
    return 1;
}

static int IsAnyItemFocused(lua_State* L){
    lua_pushboolean(L,ImGui::IsAnyItemFocused());
    return 1;
}

static int GetItemRectMin(lua_State* L){
    ImVec2 v = ImGui::GetItemRectMin();
    pushImVec2(L,v);
    return 2;
}

static int GetItemRectMax(lua_State* L){
    ImVec2 v = ImGui::GetItemRectMax();
    pushImVec2(L,v);
    return 2;
}

static int GetItemRectSize(lua_State* L){
    ImVec2 v = ImGui::GetItemRectSize();
    pushImVec2(L,v);
    return 2;
}

static int SetItemAllowOverlap(lua_State* L){
    ImGui::SetItemAllowOverlap();
    return 0;
}
//==========================================================================
// Miscellaneous Utilities
static int IsRectVisible(lua_State* L){
    if (lua_istable(L,2)){
        ImVec2 min,max;
        gettableVec2(L,1,min);
        gettableVec2(L,2,max);
        lua_pushboolean(L,ImGui::IsRectVisible(min,max));
    }else{
        ImVec2 v;
        gettableVec2(L,1,v);
        lua_pushboolean(L,ImGui::IsRectVisible(v));
    }
    return 1;
}

static int GetTime(lua_State* L){
    lua_pushnumber(L,ImGui::GetTime());
    return 1;
}

static int GetFrameCount(lua_State* L){
    lua_pushinteger(L,ImGui::GetFrameCount());
    return 1;
}
//TODO
static int GetBackgroundDrawList(lua_State* L){
    //ImGui::GetBackgroundDrawList();
    return 0;
}
//TODO
static int GetForegroundDrawList(lua_State* L){
    //ImGui::GetForegroundDrawList();
    return 0;
}
//TODO
static int GetDrawListSharedData(lua_State* L){
    //ImGui::GetDrawListSharedData();
    return 0;
}
//TODO
static int GetStyleColorName(lua_State* L){
    lua_pushstring(L,ImGui::GetStyleColorName(luaL_checkint(L,1)));
    return 1;
}
//TODO
static int SetStateStorage(lua_State* L){
    //ImGui::SetStateStorage();
    return 0;
}
//TODO
static int GetStateStorage(lua_State* L){
    //ImGui::GetStateStorage();
    return 0;
}

//TODO
static int CalcListClipping(lua_State* L){
    //ImGui::CalcListClipping();
    return 0;
}

static int BeginChildFrame(lua_State* L){
    ImVec2 v;
    gettableVec2(L,2,v);
    bool r = ImGui::BeginChildFrame(luaL_checkint(L,1),v,luaL_optint(L,3,0));
    lua_pushboolean(L,r);
    return 1;
}

static int EndChildFrame(lua_State* L){
    ImGui::EndChildFrame();
    return 0;
}
// Text Utilities
static int CalcTextSize(lua_State* L) {
    ImVec2 v = ImGui::CalcTextSize(luaL_checkstring(L, 1), NULL, luaL_optboolean(L, 2, false), luaL_optfloat(L, 3, -1.0f));
    pushImVec2(L, v);
    return 2;
}
//==========================================================================
// Color Utilities
//TODO
static int ColorConvertU32ToFloat4(lua_State* L){
    //ImGui::ColorConvertU32ToFloat4();
    return 0;
}
//TODO
static int ColorConvertFloat4ToU32(lua_State* L){
    //ImGui::ColorConvertFloat4ToU32();
    return 0;
}
//TODO
static int ColorConvertRGBtoHSV(lua_State* L){
    //ImGui::ColorConvertRGBtoHSV();
    return 0;
}
//TODO
static int ColorConvertHSVtoRGB(lua_State* L){
    //ImGui::ColorConvertHSVtoRGB();
    return 0;
}
//==========================================================================
    // Inputs Utilities: Keyboard
static int GetKeyIndex(lua_State* L){
    lua_pushinteger(L,ImGui::GetKeyIndex(luaL_checkint(L,1)));
    return 1;
}

static int IsKeyDown(lua_State* L){
    lua_pushboolean(L,ImGui::IsKeyDown(luaL_checkint(L,1)));
    return 1;
}

static int IsKeyPressed(lua_State* L){
    lua_pushboolean(L,ImGui::IsKeyPressed(luaL_checkint(L,1),luaL_optboolean(L,2,true)));
    return 1;
}

static int IsKeyReleased(lua_State* L){
    lua_pushboolean(L,ImGui::IsKeyReleased(luaL_checkint(L,1)));
    return 1;
}

static int GetKeyPressedAmount(lua_State* L){
    lua_pushinteger(L,ImGui::GetKeyPressedAmount(luaL_checkint(L,1),luaL_checkfloat(L,2),luaL_checkfloat(L,3)));
    return 1;
}

static int CaptureKeyboardFromApp(lua_State* L) {
    ImGui::CaptureKeyboardFromApp(luaL_optboolean(L, 1, true));
    return 0;
}

// Inputs Utilities: Mouse
static int IsMouseDown(lua_State* L){
    lua_pushboolean(L,ImGui::IsMouseDown(luaL_checkint(L,1)));
    return 1;
}

static int IsMouseClicked(lua_State* L) {
    lua_pushboolean(L, ImGui::IsMouseClicked(luaL_checkint(L, 1), luaL_optboolean(L, 2, false)));
    return 1;
}

static int IsMouseReleased(lua_State* L) {
    lua_pushboolean(L, ImGui::IsMouseReleased(luaL_checkint(L, 1)));
    return 1;
}

static int IsMouseDoubleClicked(lua_State* L) {
    lua_pushboolean(L, ImGui::IsMouseDoubleClicked(luaL_checkint(L, 1)));
    return 1;
}

static int IsMouseHoveringRect(lua_State* L) {
    ImVec2 min, max;
    getImVec2(L, 1, min);
    ;   getImVec2(L, 3, max);
    lua_pushboolean(L, ImGui::IsMouseHoveringRect(min, max, luaL_optboolean(L, 5, true)));
    return 1;
}

static int IsMousePosValid(lua_State* L) {
    if (lua_istable(L, 1)) {
        ImVec2 v(0, 0);
        gettableVec2(L, 1, v);
        lua_pushboolean(L, ImGui::IsMousePosValid(&v));
        settableVec2(L, 1, v);
    }
    else
        lua_pushboolean(L, ImGui::IsMousePosValid(NULL));
    return 0;
}

static int IsAnyMouseDown(lua_State* L) {
    lua_pushboolean(L, ImGui::IsAnyMouseDown());
    return 1;
}

static int GetMousePos(lua_State* L) {
    ImVec2 v = ImGui::GetMousePos();
    pushImVec2(L, v);
    return 2;
}

static int GetMousePosOnOpeningCurrentPopup(lua_State* L) {
    ImVec2 v = ImGui::GetMousePosOnOpeningCurrentPopup();
    pushImVec2(L, v);
    return 2;
}

static int IsMouseDragging(lua_State* L){
    lua_pushboolean(L,ImGui::IsMouseDragging(luaL_optint(L,1,0),luaL_optfloat(L,2,-0.1f)));
    return 1;
}

static int GetMouseDragDelta(lua_State* L){
    ImVec2 v = ImGui::GetMouseDragDelta(luaL_optint(L,1,0),luaL_optfloat(L,2,-1.0f));
    pushImVec2(L,v);
    return 2;
}

static int ResetMouseDragDelta(lua_State* L){
    ImGui::ResetMouseDragDelta(luaL_optint(L,1,0));
    return 0;
}

static int GetMouseCursor(lua_State* L){
    lua_pushinteger(L,ImGui::GetMouseCursor());
    return 1;
}

static int SetMouseCursor(lua_State* L){
    ImGui::SetMouseCursor(luaL_checkint(L,1));
    return 0;
}

static int CaptureMouseFromApp(lua_State* L){
    ImGui::CaptureMouseFromApp(luaL_optboolean(L,1,true));
    return 0;
}
//==========================================================================
// Clipboard Utilities
static int GetClipboardText(lua_State* L){
    lua_pushstring(L,ImGui::GetClipboardText());
    return 1;
}

static int SetClipboardText(lua_State* L){
    ImGui::SetClipboardText(luaL_checkstring(L,1));
    return 0;
}
//==========================================================================
// Settings/.Ini Utilities
static int LoadIniSettingsFromDisk(lua_State* L){
    ImGui::LoadIniSettingsFromDisk(luaL_checkstring(L,1));
    return 0;
}

static int LoadIniSettingsFromMemory(lua_State* L){
    ImGui::LoadIniSettingsFromMemory(luaL_checkstring(L,1),luaL_optint(L,2,0));
    return 0;
}

static int SaveIniSettingsToDisk(lua_State* L){
    ImGui::SaveIniSettingsToDisk(luaL_checkstring(L,1));
    return 0;
}

static int SaveIniSettingsToMemory(lua_State* L){
    size_t size;
    const char* r = ImGui::SaveIniSettingsToMemory(&size);
    lua_pushlstring(L,r,size);
    return 1;
}
// Memory Allocators


int bind_widgets(lua_State* L){

    luaL_Reg funcs[] = {
        {"Begin"      , Begin}      ,
        {"End"        , End}        ,
        {"BeginChild" , BeginChild} ,
        {"EndChild"   , EndChild}   ,
// Windows Utilities
        {"IsWindowAppearing" , IsWindowAppearing} ,
        {"IsWindowCollapsed" , IsWindowCollapsed} ,
        {"IsWindowFocused"   , IsWindowFocused}   ,
        {"IsWindowHovered"   , IsWindowHovered}   ,
        {"GetWindowDrawList" , GetWindowDrawList} ,
        {"GetWindowPos"      , GetWindowPos}      ,
        {"GetWindowSize"     , GetWindowSize}     ,
        {"GetWindowWidth"    , GetWindowWidth}    ,
        {"GetWindowHeight"   , GetWindowHeight}   ,
// Prefer using SetNextXXX
        {"SetNextWindowPos"             , SetNextWindowPos}             ,
        {"SetNextWindowSize"            , SetNextWindowSize}            ,
        {"SetNextWindowSizeConstraints" , SetNextWindowSizeConstraints} ,
        {"SetNextWindowContentSize"     , SetNextWindowContentSize}     ,
        {"SetNextWindowCollapsed"       , SetNextWindowCollapsed}       ,
        {"SetNextWindowFocus"           , SetNextWindowFocus}           ,
        {"SetNextWindowBgAlpha"         , SetNextWindowBgAlpha}         ,
        {"SetWindowPos"                 , SetWindowPos}                 ,
        {"SetWindowSize"                , SetWindowSize}                ,
        {"SetWindowCollapsed"           , SetWindowCollapsed}           ,
        {"SetWindowFocus"               , SetWindowFocus}               ,
        {"SetWindowFontScale"           , SetWindowFontScale}           ,
// Content region
        {"GetContentRegionMax"         , GetContentRegionMax}         ,
        {"GetContentRegionAvail"       , GetContentRegionAvail}       ,
        {"GetWindowContentRegionMin"   , GetWindowContentRegionMin}   ,
        {"GetWindowContentRegionMax"   , GetWindowContentRegionMax}   ,
        {"GetWindowContentRegionWidth" , GetWindowContentRegionWidth} ,
// Windows Scrolling
        {"GetScrollX"        , GetScrollX}        ,
        {"GetScrollY"        , GetScrollY}        ,
        {"GetScrollMaxX"     , GetScrollMaxX}     ,
        {"GetScrollMaxY"     , GetScrollMaxY}     ,
        {"SetScrollX"        , SetScrollX}        ,
        {"SetScrollY"        , SetScrollY}        ,
        {"SetScrollHereX"    , SetScrollHereX}    ,
        {"SetScrollHereY"    , SetScrollHereY}    ,
        {"SetScrollFromPosX" , SetScrollFromPosX} ,
        {"SetScrollFromPosY" , SetScrollFromPosY} ,
// Parameters stacks (shared)
        {"PushFont"               , PushFont}               ,
        {"PopFont"                , PopFont}                ,
        {"PushStyleColor"         , PushStyleColor}         ,
        {"PopStyleColor"          , PopStyleColor}          ,
        {"PushStyleVar"           , PushStyleVar}           ,
        {"PopStyleVar"            , PopStyleVar}            ,
        {"GetStyleColorVec4"      , GetStyleColorVec4}      ,
        {"GetFont"                , GetFont}                ,
        {"GetFontSize"            , GetFontSize}            ,
        {"GetFontTexUvWhitePixel" , GetFontTexUvWhitePixel} ,
        {"GetColorU32"            , GetColorU32}            ,
// Parameters stacks (current window)
        {"PushItemWidth"          , PushItemWidth}          ,
        {"PopItemWidth"           , PopItemWidth}           ,
        {"SetNextItemWidth"       , SetNextItemWidth}       ,
        {"CalcItemWidth"          , CalcItemWidth}          ,
        {"PushTextWrapPos"        , PushTextWrapPos}        ,
        {"PopTextWrapPos"         , PopTextWrapPos}         ,
        {"PushAllowKeyboardFocus" , PushAllowKeyboardFocus} ,
        {"PopAllowKeyboardFocus"  , PopAllowKeyboardFocus}  ,
        {"PushButtonRepeat"       , PushButtonRepeat}       ,
        {"PopButtonRepeat"        , PopButtonRepeat}        ,
// Cursor / Layout
        {"Separator"                    , Separator}                    ,
        {"SameLine"                     , SameLine}                     ,
        {"NewLine"                      , NewLine}                      ,
        {"Spacing"                      , Spacing}                      ,
        {"Dummy"                        , Dummy}                        ,
        {"Indent"                       , Indent}                       ,
        {"Unindent"                     , Unindent}                     ,
        {"BeginGroup"                   , BeginGroup}                   ,
        {"EndGroup"                     , EndGroup}                     ,
        {"GetCursorPos"                 , GetCursorPos}                 ,
        {"GetCursorPosX"                , GetCursorPosX}                ,
        {"GetCursorPosY"                , GetCursorPosY}                ,
        {"SetCursorPos"                 , SetCursorPos}                 ,
        {"SetCursorPosX"                , SetCursorPosX}                ,
        {"SetCursorPosY"                , SetCursorPosY}                ,
        {"GetCursorStartPos"            , GetCursorStartPos}            ,
        {"GetCursorScreenPos"           , GetCursorScreenPos}           ,
        {"SetCursorScreenPos"           , SetCursorScreenPos}           ,
        {"AlignTextToFramePadding"      , AlignTextToFramePadding}      ,
        {"GetTextLineHeight"            , GetTextLineHeight}            ,
        {"GetTextLineHeightWithSpacing" , GetTextLineHeightWithSpacing} ,
        {"GetFrameHeight"               , GetFrameHeight}               ,
        {"GetFrameHeightWithSpacing"    , GetFrameHeightWithSpacing}    ,
// ID stack/scopes
        {"PushID",PushID},
        {"PopID",PopID},
        {"GetID",GetID},
// Widgets: Text
        {"TextUnformatted" , TextUnformatted} ,
        {"Text"            , Text}            ,
        {"TextColored"     , TextColored}     ,
        {"TextDisabled"    , TextDisabled}    ,
        {"TextWrapped"     , TextWrapped}     ,
        {"LabelText"       , LabelText}       ,
        {"BulletText"      , BulletText}      ,
// Widgets: Main
        {"Button"          , Button}          ,
        {"SmallButton"     , SmallButton}     ,
        {"InvisibleButton" , InvisibleButton} ,
        {"ArrowButton"     , ArrowButton}     ,
        {"Image"           , Image}           ,
        {"ImageButton"     , ImageButton}     ,
        {"Checkbox"        , Checkbox}        ,
        {"CheckboxFlags"   , CheckboxFlags}   ,
        {"RadioButton"     , RadioButton}     ,
        {"ProgressBar"     , ProgressBar}     ,
        {"Bullet"          , Bullet}          ,
// Widgets: Combo Box
        {"BeginCombo",BeginCombo},
        {"EndCombo",EndCombo},
        {"Combo",Combo},
// Widgets: Drags
       // {"DragFloat"    , DragFloat}       ,
       //{"DragFloat2"    , DragFloat2}      ,
       //{"DragFloat3"    , DragFloat3}      ,
       // {"DragFloat4"   , DragFloat4}      ,
       {"DragFloatRange2" , DragFloatRange2} ,
       {"DragInt"         , DragInt}         ,
       {"DragInt2"        , DragInt2}        ,
       {"DragInt3"        , DragInt3}        ,
       {"DragInt4"        , DragInt4}        ,
       {"DragIntRange2"   , DragIntRange2}   ,
       //{"DragScalar"    , DragScalar}      ,
// Widgets: Sliders
        //{"SliderFloat"  , SliderFloat}   ,
        //{"SliderFloat2" , SliderFloat2}  ,
        //{"SliderFloat3" , SliderFloat3}  ,
        //{"SliderFloat4" , SliderFloat4}  ,
        {"SliderAngle"    , SliderAngle}   ,
        {"SliderInt"      , SliderInt}     ,
        {"SliderInt2"     , SliderInt2}    ,
        {"SliderInt3"     , SliderInt3}    ,
        {"SliderInt4"     , SliderInt4}    ,
        //{"SliderScalar" , SliderScalar}  ,
        {"VSliderFloat"   , VSliderFloat}  ,
        {"VSliderInt"     , VSliderInt}    ,
        {"VSliderScalar"  , VSliderScalar} ,
// Widgets: Input with Keyboard
        {"InputText"          , InputText}          ,
        {"InputTextMultiline" , InputTextMultiline} ,
        {"InputTextWithHint"  , InputTextWithHint}  ,
        {"InputFloat"         , InputFloat}         ,
        {"InputFloat2"        , InputFloat2}        ,
        {"InputFloat3"        , InputFloat3}        ,
        {"InputFloat4"        , InputFloat4}        ,
        {"InputInt"           , InputInt}           ,
        {"InputInt2"          , InputInt2}          ,
        {"InputInt3"          , InputInt3}          ,
        {"InputInt4"          , InputInt4}          ,
        {"InputDouble"        , InputDouble}        ,
        {"InputScalar"        , InputScalar}        ,
// Widgets: Color Editor/Picker
        {"ColorEdit3"          , ColorEdit3}          ,
        {"ColorEdit4"          , ColorEdit4}          ,
        {"ColorPicker3"        , ColorPicker3}        ,
        {"ColorPicker4"        , ColorPicker4}        ,
        {"ColorButton"         , ColorButton}         ,
        {"SetColorEditOptions" , SetColorEditOptions} ,
// Widgets: Trees
        {"TreeNode"                  , TreeNode}                  ,
        {"TreeNodeEx"                , TreeNodeEx}                ,
        {"TreePush"                  , TreePush}                  ,
        {"TreePop"                   , TreePop}                   ,
        {"GetTreeNodeToLabelSpacing" , GetTreeNodeToLabelSpacing} ,
        {"CollapsingHeader"          , CollapsingHeader}          ,
        {"SetNextItemOpen"           , SetNextItemOpen}           ,
// Widgets: Selectables
        {"Selectable",Selectable},
// Widgets: List Boxes
        {"ListBox"      , ListBox}      ,
        {"BeginListBox" , BeginListBox} ,
        {"EndListBox"   , EndListBox}   ,
// Widgets: Data Plotting
        {"PlotLines"     , PlotLines}     ,
        {"PlotHistogram" , PlotHistogram} ,
// Widgets: Value() Helpers.
        {"Value",Value},
// Widgets: Menus
        {"BeginMenuBar"     , BeginMenuBar}     ,
        {"EndMenuBar"       , EndMenuBar}       ,
        {"BeginMainMenuBar" , BeginMainMenuBar} ,
        {"EndMainMenuBar"   , EndMainMenuBar}   ,
        {"BeginMenu"        , BeginMenu}        ,
        {"EndMenu"          , EndMenu}          ,
        {"MenuItem"         , MenuItem}         ,
// Tooltips
        {"BeginTooltip" , BeginTooltip} ,
        {"EndTooltip"   , EndTooltip}   ,
        {"SetTooltip"   , SetTooltip}   ,
// Popups, Modals
        {"OpenPopup"               , OpenPopup}               ,
        {"BeginPopup"              , BeginPopup}              ,
        {"BeginPopupContextItem"   , BeginPopupContextItem}   ,
        {"BeginPopupContextWindow" , BeginPopupContextWindow} ,
        {"BeginPopupContextVoid"   , BeginPopupContextVoid}   ,
        {"BeginPopupModal"         , BeginPopupModal}         ,
        {"EndPopup"                , EndPopup}                ,
        {"OpenPopupOnItemClick"    , OpenPopupOnItemClick}    ,
        {"IsPopupOpen"             , IsPopupOpen}             ,
        {"CloseCurrentPopup"       , CloseCurrentPopup}       ,
 // Tables
        {"BeginTable"             , BeginTable}             ,
        {"EndTable"               , EndTable}               ,
        {"TableNextRow"           , TableNextRow}           ,
        {"TableNextColumn"        , TableNextColumn}        ,
        {"TableSetColumnIndex"    , TableSetColumnIndex}    ,
        {"TableSetupColumn"       , TableSetupColumn}       ,
        {"TableSetupScrollFreeze" , TableSetupScrollFreeze} ,
        {"TableHeadersRow"        , TableHeadersRow}        ,
        {"TableHeader"            , TableHeader}            ,
        {"TableGetSortSpecs"      , TableGetSortSpecs}      ,
        {"TableGetColumnCount"    , TableGetColumnCount}    ,
        {"TableGetColumnIndex"    , TableGetColumnIndex}    ,
        {"TableGetRowIndex"       , TableGetRowIndex}       ,
        {"TableGetColumnName"     , TableGetColumnName}     ,
        {"TableGetColumnFlags"    , TableGetColumnFlags}    ,
        {"TableSetBgColor"        , TableSetBgColor}        ,
// Columns
        {"Columns"         , Columns}         ,
        {"NextColumn"      , NextColumn}      ,
        {"GetColumnIndex"  , GetColumnIndex}  ,
        {"GetColumnWidth"  , GetColumnWidth}  ,
        {"SetColumnWidth"  , SetColumnWidth}  ,
        {"GetColumnOffset" , GetColumnOffset} ,
        {"SetColumnOffset" , SetColumnOffset} ,
        {"GetColumnsCount" , GetColumnsCount} ,
// Tab Bars, Tabs
        {"BeginTabBar"      , BeginTabBar}      ,
        {"EndTabBar"        , EndTabBar}        ,
        {"BeginTabItem"     , BeginTabItem}     ,
        {"EndTabItem"       , EndTabItem}       ,
        {"SetTabItemClosed" , SetTabItemClosed} ,
// Logging/Capture
        {"LogToTTY"       , LogToTTY}       ,
        {"LogToFile"      , LogToFile}      ,
        {"LogToClipboard" , LogToClipboard} ,
        {"LogFinish"      , LogFinish}      ,
        {"LogButtons"     , LogButtons}     ,
        {"LogText"        , LogText}        ,
// Drag and Drop
        {"BeginDragDropSource"   , BeginDragDropSource}   ,
        {"SetDragDropPayload"    , SetDragDropPayload}    ,
        {"EndDragDropSource"     , EndDragDropSource}     ,
        {"BeginDragDropTarget"   , BeginDragDropTarget}   ,
        {"AcceptDragDropPayload" , AcceptDragDropPayload} ,
        {"EndDragDropTarget"     , EndDragDropTarget}     ,
        {"GetDragDropPayload"    , GetDragDropPayload}    ,
// Clipping
        {"PushClipRect" , PushClipRect} ,
        {"PopClipRect"  , PopClipRect}  ,
// Focus, Activation
        {"SetItemDefaultFocus"  , SetItemDefaultFocus}  ,
        {"SetKeyboardFocusHere" , SetKeyboardFocusHere} ,
// Item/Widgets Utilities
        {"IsItemHovered"              , IsItemHovered}              ,
        {"IsItemActive"               , IsItemActive}               ,
        {"IsItemFocused"              , IsItemFocused}              ,
        {"IsItemClicked"              , IsItemClicked}              ,
        {"IsItemVisible"              , IsItemVisible}              ,
        {"IsItemEdited"               , IsItemEdited}               ,
        {"IsItemActivated"            , IsItemActivated}            ,
        {"IsItemDeactivated"          , IsItemDeactivated}          ,
        {"IsItemDeactivatedAfterEdit" , IsItemDeactivatedAfterEdit} ,
        {"IsItemToggledOpen"          , IsItemToggledOpen}          ,
        {"IsAnyItemHovered"           , IsAnyItemHovered}           ,
        {"IsAnyItemActive"            , IsAnyItemActive}            ,
        {"IsAnyItemFocused"           , IsAnyItemFocused}           ,
        {"GetItemRectMin"             , GetItemRectMin}             ,
        {"GetItemRectMax"             , GetItemRectMax}             ,
        {"GetItemRectSize"            , GetItemRectSize}            ,
        {"SetItemAllowOverlap"        , SetItemAllowOverlap}        ,
// Miscellaneous Utilities
        {"IsRectVisible"         , IsRectVisible}         ,
        {"GetTime"               , GetTime}               ,
        {"GetFrameCount"         , GetFrameCount}         ,
        {"GetBackgroundDrawList" , GetBackgroundDrawList} ,
        {"GetForegroundDrawList" , GetForegroundDrawList} ,
        {"GetDrawListSharedData" , GetDrawListSharedData} ,
        {"GetStyleColorName"     , GetStyleColorName}     ,
        {"SetStateStorage"       , SetStateStorage}       ,
        {"GetStateStorage"       , GetStateStorage}       ,
        {"CalcTextSize"          , CalcTextSize}          ,
        {"CalcListClipping"      , CalcListClipping}      ,
        {"BeginChildFrame"       , BeginChildFrame}       ,
        {"EndChildFrame"         , EndChildFrame}         ,
// Color Utilities
        {"ColorConvertU32ToFloat4" , ColorConvertU32ToFloat4} ,
        {"ColorConvertFloat4ToU32" , ColorConvertFloat4ToU32} ,
        {"ColorConvertRGBtoHSV"    , ColorConvertRGBtoHSV}    ,
        {"ColorConvertHSVtoRGB"    , ColorConvertHSVtoRGB}    ,
// Inputs Utilities
        {"GetKeyIndex"                      , GetKeyIndex}                      ,
        {"IsKeyDown"                        , IsKeyDown}                        ,
        {"IsKeyPressed"                     , IsKeyPressed}                     ,
        {"IsKeyReleased"                    , IsKeyReleased}                    ,
        {"GetKeyPressedAmount"              , GetKeyPressedAmount}              ,
        {"IsMouseDown"                      , IsMouseDown}                      ,
        {"IsAnyMouseDown"                   , IsAnyMouseDown}                   ,
        {"IsMouseClicked"                   , IsMouseClicked}                   ,
        {"IsMouseDoubleClicked"             , IsMouseDoubleClicked}             ,
        {"IsMouseReleased"                  , IsMouseReleased}                  ,
        {"IsMouseDragging"                  , IsMouseDragging}                  ,
        {"IsMouseHoveringRect"              , IsMouseHoveringRect}              ,
        {"IsMousePosValid"                  , IsMousePosValid}                  ,
        {"GetMousePos"                      , GetMousePos}                      ,
        {"GetMousePosOnOpeningCurrentPopup" , GetMousePosOnOpeningCurrentPopup} ,
        {"GetMouseDragDelta"                , GetMouseDragDelta}                ,
        {"ResetMouseDragDelta"              , ResetMouseDragDelta}              ,
        {"GetMouseCursor"                   , GetMouseCursor}                   ,
        {"SetMouseCursor"                   , SetMouseCursor}                   ,
        {"CaptureKeyboardFromApp"           , CaptureKeyboardFromApp}           ,
        {"CaptureMouseFromApp"              , CaptureMouseFromApp}              ,
// Clipboard Utilities
        {"GetClipboardText",GetClipboardText},
        {"SetClipboardText",SetClipboardText},
// Settings/.Ini Utilities
        {"LoadIniSettingsFromDisk"   , LoadIniSettingsFromDisk}   ,
        {"LoadIniSettingsFromMemory" , LoadIniSettingsFromMemory} ,
        {"SaveIniSettingsToDisk"     , SaveIniSettingsToDisk}     ,
        {"SaveIniSettingsToMemory"   , SaveIniSettingsToMemory}   ,
// Memory Allocators

        {NULL, NULL},
    };
    luaL_setfuncs(L, funcs, 0);
    return 0;
}